using System;
using System.Collections.Generic;
using System.ComponentModel;

using LongNet.Util;

namespace LongNet.Config
{
    /// <summary>
    /// Represents a configuration element for <see cref="T:ConnectSocketPool"/> used in <see cref="T:MemcachedNode"/>. 
    /// This class cannot be inherited. 
    /// </summary>
    public class MemcachedSocketPoolElement
    {
        #region Constants

        internal const string LocalName = "socketPool";

        internal static class PropertyName
        {
            internal const string MinPoolSize = "minPoolSize";
            internal const string MaxPoolSize = "maxPoolSize";
            internal const string ConnectTimeout = "connectTimeout";
            internal const string SendTimeout = "sendTimeout";
            internal const string ReceiveTimeout = "receiveTimeout";
            internal const string DeadTimeout = "deadTimeout";
        }

        #endregion

        #region Fields

        private int minPoolSize = 10;
        private int maxPoolSize = 200;
        private TimeSpan connectTimeout = new TimeSpan(0, 0, 10);
        private TimeSpan sendTimeout = new TimeSpan(0, 0, 10);
        private TimeSpan receiveTimeout = new TimeSpan(0, 0, 10);
        private TimeSpan deadTimeout = new TimeSpan(0, 2, 0);

        #endregion

        #region Constructors

        internal MemcachedSocketPoolElement()
        {
        }

        internal MemcachedSocketPoolElement(int minPoolSize, int maxPoolSize, TimeSpan connectTimeout, TimeSpan sendTimeout, TimeSpan receiveTimeout, TimeSpan deadTimeout)
        {
            this.MinPoolSize = minPoolSize;
            this.MaxPoolSize = maxPoolSize;
            this.ConnectTimeout = connectTimeout;
            this.SendTimeout = sendTimeout;
            this.ReceiveTimeout = receiveTimeout;
            this.DeadTimeout = deadTimeout;
        }

        #endregion

        #region Setting Properties

        /// <summary>
        /// Gets the MinPoolSize of <see cref="T:ConnectSocketPool"/> configuration.
        /// The value is <c>10</c> by default and must in range [0, 1000].
        /// </summary>
        public int MinPoolSize
        {
            get { return this.minPoolSize; }
            internal set
            {
                if (value < 0 || value > 1000)
                    throw new ArgumentOutOfRangeException("MinPoolSize", "MinPoolSize must in range [0,1000].");

                this.minPoolSize = value;
            }
        }

        /// <summary>
        /// Gets the MinPoolSize of <see cref="T:ConnectSocketPool"/> configuration.
        /// The value is <c>10</c> by default and must in range [<see cref="F:MinPoolSize"/>, 1000].
        /// </summary>
        public int MaxPoolSize
        {
            get { return this.maxPoolSize; }
            internal set
            {
                if (value < this.minPoolSize || value > 1000)
                    throw new ArgumentOutOfRangeException("MaxPoolSize", "MaxPoolSize must in range [MinPoolSize,1000].");

                this.maxPoolSize = value;
            }
        }

        /// <summary>
        /// Gets the ConnectTimeout of <see cref="T:ConnectSocketPool"/> configuration.
        /// The value is <c>00:00:10</c>(10 seconds) by default.
        /// </summary>
        public TimeSpan ConnectTimeout
        {
            get { return this.connectTimeout; }
            internal set
            {
                if (value == null || value <= TimeSpan.Zero)
                    throw new ArgumentOutOfRangeException("ConnectTimeout", "ConnectTimeout must not be null and should greater than TimeSpan.Zero.");

                this.connectTimeout = value;
            }
        }

        /// <summary>
        /// Gets the SendTimeout of <see cref="T:ConnectSocketPool"/> configuration.
        /// The value is <c>00:00:10</c>(10 seconds) by default.
        /// </summary>
        public TimeSpan SendTimeout
        {
            get { return this.sendTimeout; }
            internal set
            {
                if (value == null || value <= TimeSpan.Zero)
                    throw new ArgumentOutOfRangeException("SendTimeout", "SendTimeout must not be null and should greater than TimeSpan.Zero.");

                this.sendTimeout = value;
            }
        }

        /// <summary>
        /// Gets the ReceiveTimeout of <see cref="T:ConnectSocketPool"/> configuration.
        /// The value is <c>00:00:10</c>(10 seconds) by default.
        /// </summary>
        public TimeSpan ReceiveTimeout
        {
            get { return this.receiveTimeout; }
            internal set
            {
                if (value == null || value <= TimeSpan.Zero)
                    throw new ArgumentOutOfRangeException("ReceiveTimeout", "ReceiveTimeout must not be null and should greater than TimeSpan.Zero.");

                this.receiveTimeout = value;
            }
        }

        /// <summary>
        /// Gets the DeadTimeout of <see cref="T:ConnectSocketPool"/> configuration.
        /// The value is <c>00:05:00</c>(5 minutes) by default.
        /// </summary>
        public TimeSpan DeadTimeout
        {
            get { return this.deadTimeout; }
            internal set
            {
                if (value == null || value <= TimeSpan.Zero)
                    throw new ArgumentOutOfRangeException("DeadTimeout", "DeadTimeout must not be null and should greater than TimeSpan.Zero.");

                this.deadTimeout = value;
            }
        }

        #endregion
    }
}
